home *** CD-ROM | disk | FTP | other *** search
/ Aminet 31 / Aminet 31 (1999)(Schatztruhe)[!][Jun 1999].iso / Aminet / dev / c / vbccwossrc.lha / vbcc / pasm / pass.c < prev    next >
C/C++ Source or Header  |  1999-03-07  |  13KB  |  480 lines

  1. /* $VER: pasm pass.c V1.1b (05.07.98)
  2.  *
  3.  * This file is part of pasm, a portable PowerPC assembler.
  4.  * Copyright (c) 1997-98  Frank Wille
  5.  *
  6.  * pasm is freeware and part of the portable and retargetable ANSI C
  7.  * compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann.
  8.  * pasm may be freely redistributed as long as no modifications are
  9.  * made and nothing is charged for it. Non-commercial usage is allowed
  10.  * without any restrictions.
  11.  * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
  12.  * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
  13.  *
  14.  *
  15.  * v1.1b  (05.07.98) phx
  16.  *        Removed pasm-version symbol.
  17.  * v1.0   (14.04.98) phx
  18.  *        Non-global labels have local binding now. They had none before
  19.  *        and therefore didn't appear in object files.
  20.  * v0.8   (14.02.98) phx
  21.  *        Alignment list for each section. This fixes the problems
  22.  *        with optimizations.
  23.  * v0.7   (02.01.98) phx
  24.  *        Allow more than two assembler passes, as required for
  25.  *        optimizations.
  26.  * v0.6   (26.10.97) phx
  27.  *        Bug in conditional assembly fixed.
  28.  *        @object and @function symbols are always defined before
  29.  *        pass 1 is executed.
  30.  * v0.5   (12.10.97) phx
  31.  *        Support for user symbol definitions by -D option.
  32.  *        The opcode field is automatically converted to lower case,
  33.  *        so upper case directives and instructions are also allowed.
  34.  * v0.3   (10.04.97) phx
  35.  *        Some vbcc-specific changes.
  36.  * v0.2   (25.03.97) phx
  37.  *        Writes ELF object for 32-bit PowerPC big-endian. Either absolute
  38.  *        or ELF output format may be selected. ELF is default for all
  39.  *        currently supported platforms. PPCasm supports nine different
  40.  *        relocation types (there are much more...).
  41.  *        Compiles and works also under NetBSD/amiga (68k).
  42.  *        Changed function declaration to 'new style' in all sources
  43.  *        (to avoid problems with '...' for example).
  44.  * v0.1   (11.03.97) phx
  45.  *        First test version with all PowerPC instructions and most
  46.  *        important directives. Only raw, absolute output.
  47.  * v0.0   (15.02.97) phx
  48.  *        File created.
  49.  */
  50.  
  51.  
  52. #define PASS_C
  53. #include "ppcasm.h"
  54.  
  55.  
  56. void exec_pass1(struct GlobalVars *);
  57. void pass1(struct GlobalVars *,struct SourceText *,
  58.            struct MacroParams *,struct SourceThread *);
  59. struct SourceText *include_source(struct GlobalVars *,char *);
  60. void exec_pass2(struct GlobalVars *);
  61. void pass2(struct GlobalVars *,struct SourceText *,
  62.            struct MacroParams *,struct SourceThread *);
  63. struct SourceText *get_source(struct GlobalVars *);
  64.  
  65. static char *insert_macro_params(struct GlobalVars *,struct ParsedLine *,
  66.                                  char *,struct MacroParams *);
  67. static char *readline(struct GlobalVars *,struct ParsedLine *,char *);
  68. static char *getlabel(struct GlobalVars *,char *);
  69. static struct SourceText *add_source(struct GlobalVars *,char *,char *,long);
  70. static void prepare_sections(struct GlobalVars *);
  71.  
  72.  
  73.  
  74. void exec_pass1(struct GlobalVars *gv)
  75. {
  76.   struct Symbol *sym;
  77.   char **p,*xmnemobuf,*usrdefbuf;
  78.   size_t xmsize=0,udsize=0;
  79.   struct UserDefine *nextudn;
  80.   struct UserDefine *udn = (struct UserDefine *)gv->userdeflist.first;
  81.   struct Section dummySec;
  82.  
  83.   memset(&dummySec,0,sizeof(struct Section));
  84.   gv->csect = &dummySec;  /* to avoid SEGVs during start up */
  85.   gv->lcsym = add_symbol(gv,"$",SYM_RELOC,0);
  86.   gv->nargsym = add_symbol(gv,"$NARG",SYM_ABS,0);
  87.   add_symbol(gv,"@object",SYM_ABS,1);
  88.   add_symbol(gv,"@function",SYM_ABS,2);
  89.   gv->ifcond[0] = TRUE;
  90.  
  91.   pass1(gv,add_source(gv,"<standard sections>",stdsects,
  92.         strlen(stdsects)),NULL,NULL);
  93.  
  94.   if (!gv->noregsymbols)
  95.     pass1(gv,add_source(gv,"<standard definitions>",stdsets,
  96.           strlen(stdsets)),NULL,NULL);
  97.  
  98.   while (nextudn = (struct UserDefine *)udn->n.next) {
  99.     udsize += strlen(udn->line);
  100.     udn = nextudn;
  101.   }
  102.   if (udsize) {
  103.     usrdefbuf = alloc(udsize+1);
  104.     *usrdefbuf = 0;
  105.     while (udn = (struct UserDefine *)remhead(&gv->userdeflist)) {
  106.       strcat(usrdefbuf,udn->line);
  107.       free(udn->line);
  108.       free(udn);
  109.     }
  110.     gv->usrdefs = TRUE;
  111.     pass1(gv,add_source(gv,"<user definitions>",usrdefbuf,udsize),
  112.           NULL,NULL);
  113.   }
  114.  
  115.   if (!gv->noextmnemo) {
  116.     p = xmnemos;
  117.     while (*p) {
  118.       xmsize += strlen(*p);
  119.       p++;
  120.     }
  121.     xmnemobuf = alloc(xmsize+1);
  122.     *xmnemobuf = 0;
  123.     p = xmnemos;
  124.     while (*p) {
  125.       strcat(xmnemobuf,*p);
  126.       p++;
  127.     }
  128.     pass1(gv,add_source(gv,"<extended mnemonics>",xmnemobuf,xmsize),
  129.           NULL,NULL);
  130.   }
  131.  
  132.   pass1(gv,include_source(gv,gv->source_name),NULL,NULL);
  133.   if (gv->vc) {
  134.     activate_section(gv,(struct Section *)gv->sectionlist.first);
  135.     alignment(gv,2);
  136.     pcadd(gv,4);
  137.   }
  138. }
  139.  
  140.  
  141. void pass1(struct GlobalVars *gv,struct SourceText *srctxt,
  142.            struct MacroParams *macro,struct SourceThread *prev_st)
  143. /* Assembler Pass 1 */
  144. {
  145.   struct SourceThread st;
  146.   unsigned long nlines = srctxt->nlines;
  147.   char *lp,c;
  148.   struct ParsedLine *pl = srctxt->plin;
  149.  
  150.   /* init SourceThread structure */
  151.   st.prev = prev_st;
  152.   st.macro = macro;
  153.   st.csource = srctxt;
  154.   st.srcptr = srctxt->text;  /* current source pointer */
  155.   st.line = 1;
  156.   st.macskip = NULL;
  157.   gv->cthread = &st;  /* set current source thread */
  158.  
  159.   while (nlines--) {
  160.     gv->absline++;
  161.     pl->lineptr = st.lineptr = st.srcptr;
  162.  
  163.     /* get next line of source text */
  164.     if (macro && gv->ifcond[gv->iflevel]) {  /* insert macro parameters? */
  165.       st.srcptr = insert_macro_params(gv,pl,st.srcptr,macro);
  166.     }
  167.     else {
  168.       st.srcptr = readline(gv,pl,st.srcptr);
  169.     }
  170.     lp = gv->linebuf;
  171.  
  172.     /* evaluate label field */
  173.     lp = getlabel(gv,lp);
  174.     if (*gv->strbuf)
  175.       if (!st.macskip && gv->ifcond[gv->iflevel]) {
  176.         struct Symbol *sym;
  177.         sym = add_symbol(gv,gv->strbuf,SYM_RELOC,gv->csect->pc);
  178.         if (!sym->bind)
  179.           /* labels have always local binding first */
  180.           sym->bind = SYMB_LOCAL;
  181.       }
  182.     lp = skipspaces(lp);
  183.  
  184.     /* evaluate opcode field */
  185.     lp = getsymbol(gv,lp);
  186.     if (*gv->strbuf) {
  187.       lower_case(gv->strbuf);  /* convert opcode to lower case */
  188.  
  189.       if (st.macskip) {  /* macros */
  190.         if (!strcmp(gv->strbuf,".endm")) {
  191.           st.macskip->nlines = gv->absline - st.macskip->nlines;
  192.           add_macro(gv,st.macskip);
  193.           st.macskip = NULL;
  194.         }
  195.       }
  196.  
  197.       else if (!gv->ifcond[gv->iflevel]) {  /* conditional assembly */
  198.         if (!strncmp(gv->strbuf,".if",3))
  199.           gv->ifignore++;
  200.         else if (!strcmp(gv->strbuf,".else")) {
  201.           if (gv->ifignore == 0)
  202.             gv->ifcond[gv->iflevel] = TRUE;
  203.         }
  204.         else if (!strcmp(gv->strbuf,".endif")) {
  205.           if (gv->ifignore)
  206.             gv->ifignore--;
  207.           else
  208.             gv->iflevel--;
  209.         }
  210.       }
  211.  
  212.       else {  /* search opcode */
  213.         c = *lp;  /* branch hint given? */
  214.         if (c=='+') {
  215.           lp++;
  216.           pl->branch_hint = 1;
  217.         }
  218.         else if (c=='-') {
  219.           lp++;
  220.           pl->branch_hint = -1;
  221.         }
  222.         search_opcode(gv,pl,gv->strbuf,skipspaces(lp));
  223.       }
  224.     }
  225.  
  226.     if (!(pl->flags&PLF_NONEWLINE))
  227.       st.line++;
  228.     ++pl;
  229.   }
  230.   gv->cthread = prev_st;
  231. }
  232.  
  233.  
  234. static char *insert_macro_params(struct GlobalVars *gv,struct ParsedLine *pl,
  235.                                  char *s,struct MacroParams *mp)
  236. {
  237.   char **par = mp->param;
  238.   char c,callidbuf[16];
  239.   char *pp,*d=gv->linebuf;
  240.   int n;
  241.  
  242.   do {
  243.     if ((c=*s++) == '\\') {
  244.       if (*s>='0' && *s<='9') {  /* macro parameter? */
  245.         n = (int)(*s++ - '0');
  246.         if (pp = par[n]) {
  247.           while (*d++ = *pp++);  /* insert parameter */
  248.           d--;
  249.           continue;
  250.         }
  251.         else {
  252.           error(9,n);  /* reference to undefined macro parameter n */
  253.           continue;
  254.         }
  255.       }
  256.       else if (*s=='@') {  /* insert macro call id */
  257.         s++;
  258.         pp = callidbuf;
  259.         sprintf(pp,"$%d",(int)mp->call_id);
  260.         while (*d++ = *pp++);
  261.         d--;
  262.         continue;
  263.       }
  264.     }
  265.     *d++ = c;
  266.   }
  267.   while (c!=0 && c!=1);
  268.   if (c==1) {
  269.     *(--d) = 0;
  270.     pl->flags |= PLF_NONEWLINE;
  271.   }
  272.   return (s);
  273. }
  274.  
  275.  
  276. static char *readline(struct